1 /* Copyright 2002-2016 CS Systèmes d'Information
2 * Licensed to CS Systèmes d'Information (CS) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * CS licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.orekit.files.ccsds;
19
20 import java.util.AbstractList;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.LinkedHashSet;
25 import java.util.List;
26 import java.util.ListIterator;
27 import java.util.Set;
28
29 import org.hipparchus.geometry.euclidean.threed.Vector3D;
30 import org.hipparchus.linear.RealMatrix;
31 import org.hipparchus.util.Pair;
32 import org.orekit.errors.OrekitException;
33 import org.orekit.errors.OrekitMessages;
34 import org.orekit.files.general.OrbitFile;
35 import org.orekit.files.general.SatelliteInformation;
36 import org.orekit.files.general.SatelliteTimeCoordinate;
37 import org.orekit.frames.Frame;
38 import org.orekit.frames.LOFType;
39 import org.orekit.orbits.CartesianOrbit;
40 import org.orekit.time.AbsoluteDate;
41
42 /** This class stocks all the information of the OEM File parsed by OEMParser. It
43 * contains the header and a list of Ephemerides Blocks each containing
44 * metadata, a list of ephemerides data lines and optional covariance matrices
45 * (and their metadata).
46 * @author sports
47 * @since 6.1
48 */
49 public class OEMFile extends ODMFile {
50
51 /** List of ephemeris blocks. */
52 private List<EphemeridesBlock> ephemeridesBlocks;
53
54 /** OEMFile constructor. */
55 public OEMFile() {
56 ephemeridesBlocks = new ArrayList<EphemeridesBlock>();
57 }
58
59 /** Add a block to the list of ephemeris blocks. */
60 void addEphemeridesBlock() {
61 ephemeridesBlocks.add(new EphemeridesBlock());
62 }
63
64 /**Get the list of ephemerides blocks as an unmodifiable list.
65 * @return the list of ephemerides blocks
66 */
67 public List<EphemeridesBlock> getEphemeridesBlocks() {
68 return Collections.unmodifiableList(ephemeridesBlocks);
69 }
70
71 /** Check that, according to the CCSDS standard, every OEMBlock has the same time system.
72 * @exception OrekitException if some blocks do not have the same time system
73 */
74 void checkTimeSystems() throws OrekitException {
75 final OrbitFile.TimeSystem timeSystem = getEphemeridesBlocks().get(0).getMetaData().getTimeSystem();
76 for (final EphemeridesBlock block : ephemeridesBlocks) {
77 if (!timeSystem.equals(block.getMetaData().getTimeSystem())) {
78 throw new OrekitException(OrekitMessages.CCSDS_OEM_INCONSISTENT_TIME_SYSTEMS,
79 timeSystem, block.getMetaData().getTimeSystem());
80 }
81 }
82 }
83
84 /** {@inheritDoc}
85 * <p>
86 * We return here only the coordinate systems of the first ephemerides block.
87 * </p>
88 */
89 @Override
90 public String getCoordinateSystem() {
91 return ephemeridesBlocks.get(0).getMetaData().getFrame().toString();
92 }
93
94 /** {@inheritDoc} */
95 @Override
96 public OrbitFile.TimeSystem getTimeSystem() {
97 return ephemeridesBlocks.get(0).getMetaData().getTimeSystem();
98 }
99
100 /** {@inheritDoc}
101 * <p>
102 * We return here only the start time of the first ephemerides block.
103 * </p>
104 */
105 @Override
106 public AbsoluteDate getEpoch() {
107 return ephemeridesBlocks.get(0).getStartTime();
108 }
109
110 /** {@inheritDoc} */
111 @Override
112 public Collection<SatelliteInformation> getSatellites() {
113 final Set<String> availableSatellites = getAvailableSatelliteIds();
114 final List<SatelliteInformation> satellites =
115 new ArrayList<SatelliteInformation>(availableSatellites.size());
116 for (String satId : availableSatellites) {
117 satellites.add(new SatelliteInformation(satId));
118 }
119 return satellites;
120 }
121
122 /** {@inheritDoc} */
123 @Override
124 public int getSatelliteCount() {
125 return getAvailableSatelliteIds().size();
126 }
127
128 /** {@inheritDoc} */
129 @Override
130 public SatelliteInformation getSatellite(final String satId) {
131 final Set<String> availableSatellites = getAvailableSatelliteIds();
132 if (availableSatellites.contains(satId)) {
133 return new SatelliteInformation(satId);
134 } else {
135 return null;
136 }
137 }
138
139 /** {@inheritDoc} */
140 @Override
141 public List<SatelliteTimeCoordinate> getSatelliteCoordinates(final String satId) {
142 // first we collect all available EphemeridesBlocks for this satellite
143 // and return a list view of the actual EphemeridesBlocks transforming the
144 // EphemeridesDataLines into SatelliteTimeCoordinates in a lazy manner.
145 final List<Pair<Integer, Integer>> ephemeridesBlockMapping = new ArrayList<Pair<Integer, Integer>>();
146 final ListIterator<EphemeridesBlock> it = ephemeridesBlocks.listIterator();
147 int totalDataLines = 0;
148 while (it.hasNext()) {
149 final int index = it.nextIndex();
150 final EphemeridesBlock block = it.next();
151
152 if (block.getMetaData().getObjectID().equals(satId)) {
153 final int dataLines = block.getEphemeridesDataLines().size();
154 totalDataLines += dataLines;
155 ephemeridesBlockMapping.add(new Pair<Integer, Integer>(index, dataLines));
156 }
157 }
158
159 // the total number of coordinates for this satellite
160 final int totalNumberOfCoordinates = totalDataLines;
161
162 return new AbstractList<SatelliteTimeCoordinate>() {
163
164 @Override
165 public SatelliteTimeCoordinate get(final int index) {
166 if (index < 0 || index >= size()) {
167 throw new IndexOutOfBoundsException();
168 }
169
170 // find the corresponding ephemerides block and data line
171 int ephemeridesBlockIndex = -1;
172 int dataLineIndex = index;
173 for (Pair<Integer, Integer> pair : ephemeridesBlockMapping) {
174 if (dataLineIndex < pair.getValue()) {
175 ephemeridesBlockIndex = pair.getKey();
176 break;
177 } else {
178 dataLineIndex -= pair.getValue();
179 }
180 }
181
182 if (ephemeridesBlockIndex == -1 || dataLineIndex == -1) {
183 throw new IndexOutOfBoundsException();
184 }
185
186 final EphemeridesDataLine dataLine =
187 ephemeridesBlocks.get(ephemeridesBlockIndex).getEphemeridesDataLines().get(dataLineIndex);
188 final CartesianOrbit orbit = dataLine.getOrbit();
189 return new SatelliteTimeCoordinate(orbit.getDate(), orbit.getPVCoordinates());
190 }
191
192 @Override
193 public int size() {
194 return totalNumberOfCoordinates;
195 }
196
197 };
198 }
199
200 /** Returns a set of all available satellite Ids in this OEMFile.
201 * @return a set of all available satellite Ids
202 */
203 private Set<String> getAvailableSatelliteIds() {
204 final Set<String> availableSatellites = new LinkedHashSet<String>();
205 for (EphemeridesBlock block : ephemeridesBlocks) {
206 availableSatellites.add(block.getMetaData().getObjectID());
207 }
208 return availableSatellites;
209 }
210
211 /** The Ephemerides Blocks class contain metadata, the list of ephemerides data
212 * lines and optional covariance matrices (and their metadata). The reason
213 * for which the ephemerides have been separated into blocks is that the
214 * ephemerides of two different blocks are not suited for interpolation.
215 * @author sports
216 */
217 public class EphemeridesBlock {
218
219 /** Meta-data for the block. */
220 private ODMMetaData metaData;
221
222 /** Start of total time span covered by ephemerides data and covariance
223 * data. */
224 private AbsoluteDate startTime;
225
226 /** End of total time span covered by ephemerides data and covariance
227 * data. */
228 private AbsoluteDate stopTime;
229
230 /** Start of useable time span covered by ephemerides data, it may be
231 * necessary to allow for proper interpolation. */
232 private AbsoluteDate useableStartTime;
233
234 /** End of useable time span covered by ephemerides data, it may be
235 * necessary to allow for proper interpolation. */
236 private AbsoluteDate useableStopTime;
237
238 /** The interpolation method to be used. */
239 private String interpolationMethod;
240
241 /** The interpolation degree. */
242 private int interpolationDegree;
243
244 /** List of ephemerides data lines. */
245 private List<EphemeridesDataLine> ephemeridesDataLines;
246
247 /** List of covariance matrices. */
248 private List<CovarianceMatrix> covarianceMatrices;
249
250 /** Tests whether the reference frame has an epoch associated to it. */
251 private boolean hasRefFrameEpoch;
252
253 /** Ephemerides Data Lines comments. The list contains a string for each
254 * line of comment. */
255 private List<String> ephemeridesDataLinesComment;
256
257 /** EphemeridesBlock constructor. */
258 public EphemeridesBlock() {
259 metaData = new ODMMetaData(OEMFile.this);
260 ephemeridesDataLines = new ArrayList<EphemeridesDataLine>();
261 covarianceMatrices = new ArrayList<CovarianceMatrix>();
262 }
263
264 /** Get the list of Ephemerides data lines.
265 * @return the list of Ephemerides data lines
266 */
267 public List<EphemeridesDataLine> getEphemeridesDataLines() {
268 return ephemeridesDataLines;
269 }
270
271 /** Get the list of Covariance Matrices.
272 * @return the list of Covariance Matrices
273 */
274 public List<CovarianceMatrix> getCovarianceMatrices() {
275 return covarianceMatrices;
276 }
277
278 /** Get the meta-data for the block.
279 * @return meta-data for the block
280 */
281 public ODMMetaData getMetaData() {
282 return metaData;
283 }
284
285 /** Get start of total time span covered by ephemerides data and
286 * covariance data.
287 * @return the start time
288 */
289 public AbsoluteDate getStartTime() {
290 return startTime;
291 }
292
293 /** Set start of total time span covered by ephemerides data and
294 * covariance data.
295 * @param startTime the time to be set
296 */
297 void setStartTime(final AbsoluteDate startTime) {
298 this.startTime = startTime;
299 }
300
301 /** Get end of total time span covered by ephemerides data and covariance
302 * data.
303 * @return the stop time
304 */
305 public AbsoluteDate getStopTime() {
306 return stopTime;
307 }
308
309 /** Set end of total time span covered by ephemerides data and covariance
310 * data.
311 * @param stopTime the time to be set
312 */
313 void setStopTime(final AbsoluteDate stopTime) {
314 this.stopTime = stopTime;
315 }
316
317 /** Get start of useable time span covered by ephemerides data, it may be
318 * necessary to allow for proper interpolation.
319 * @return the useable start time
320 */
321 public AbsoluteDate getUseableStartTime() {
322 return useableStartTime;
323 }
324
325 /** Set start of useable time span covered by ephemerides data, it may be
326 * necessary to allow for proper interpolation.
327 * @param useableStartTime the time to be set
328 */
329 void setUseableStartTime(final AbsoluteDate useableStartTime) {
330 this.useableStartTime = useableStartTime;
331 }
332
333 /** Get end of useable time span covered by ephemerides data, it may be
334 * necessary to allow for proper interpolation.
335 * @return the useable stop time
336 */
337 public AbsoluteDate getUseableStopTime() {
338 return useableStopTime;
339 }
340
341 /** Set end of useable time span covered by ephemerides data, it may be
342 * necessary to allow for proper interpolation.
343 * @param useableStopTime the time to be set
344 */
345 void setUseableStopTime(final AbsoluteDate useableStopTime) {
346 this.useableStopTime = useableStopTime;
347 }
348
349 /** Get the interpolation method to be used.
350 * @return the interpolation method
351 */
352 public String getInterpolationMethod() {
353 return interpolationMethod;
354 }
355
356 /** Set the interpolation method to be used.
357 * @param interpolationMethod the interpolation method to be set
358 */
359 void setInterpolationMethod(final String interpolationMethod) {
360 this.interpolationMethod = interpolationMethod;
361 }
362
363 /** Get the interpolation degree.
364 * @return the interpolation degree
365 */
366 public int getInterpolationDegree() {
367 return interpolationDegree;
368 }
369
370 /** Set the interpolation degree.
371 * @param interpolationDegree the interpolation degree to be set
372 */
373 void setInterpolationDegree(final int interpolationDegree) {
374 this.interpolationDegree = interpolationDegree;
375 }
376
377 /** Get boolean testing whether the reference frame has an epoch associated to it.
378 * @return true if the reference frame has an epoch associated to it
379 * false otherwise
380 */
381 public boolean getHasRefFrameEpoch() {
382 return hasRefFrameEpoch;
383 }
384
385 /** Set boolean testing whether the reference frame has an epoch associated to it.
386 * @param hasRefFrameEpoch the boolean to be set.
387 */
388 void setHasRefFrameEpoch(final boolean hasRefFrameEpoch) {
389 this.hasRefFrameEpoch = hasRefFrameEpoch;
390 }
391
392 /** Get the ephemerides data lines comment.
393 * @return the comment
394 */
395 public List<String> getEphemeridesDataLinesComment() {
396 return ephemeridesDataLinesComment;
397 }
398
399 /** Set the ephemerides data lines comment.
400 * @param ephemeridesDataLinesComment the comment to be set
401 */
402 void setEphemeridesDataLinesComment(final List<String> ephemeridesDataLinesComment) {
403 this.ephemeridesDataLinesComment = new ArrayList<String>(ephemeridesDataLinesComment);
404 }
405 }
406
407 /** The EphemeridesDataLine class represents the content of an OEM ephemerides
408 * data line and consists of a cartesian orbit and an optional acceleration
409 * vector.
410 * @author sports
411 */
412 public static class EphemeridesDataLine {
413
414 /** The cartesian orbit relative to the ephemeris. */
415 private CartesianOrbit orbit;
416
417 /** The acceleration vector. */
418 private Vector3D acceleration;
419
420 /** The EphemeridesDataLine constructor.
421 * @param orbit the orbit corresponding to the ephemeris
422 * @param acceleration the acceleration vector
423 */
424 EphemeridesDataLine(final CartesianOrbit orbit, final Vector3D acceleration) {
425 this.acceleration = acceleration;
426 this.orbit = orbit;
427 }
428
429 /** Get the ephemerides data line orbit.
430 * @return the orbit
431 */
432 public CartesianOrbit getOrbit() {
433 return orbit;
434 }
435
436 /** Get the ephemerides data line acceleration vector.
437 * @return the acceleration vector
438 */
439 public Vector3D getAcceleration() {
440 return acceleration;
441 }
442
443 }
444
445 /** The CovarianceMatrix class represents a covariance matrix and its
446 * metadata: epoch and frame.
447 * @author sports
448 */
449 public static class CovarianceMatrix {
450
451 /** Covariance matrix. */
452 private RealMatrix matrix;
453
454 /** Epoch relative to the covariance matrix. */
455 private AbsoluteDate epoch;
456
457 /** Coordinate system for covariance matrix, for Local Orbital Frames. */
458 private LOFType lofType;
459
460 /** Coordinate system for covariance matrix, for absolute frames.
461 * If not given it is set equal to refFrame. */
462 private Frame frame;
463
464 /** Covariance Matrix constructor.
465 * @param epoch the epoch
466 * @param lofType coordinate system for covariance matrix, for Local Orbital Frames
467 * @param frame coordinate system for covariance matrix, for absolute frames
468 * @param lastMatrix the covariance matrix
469 */
470 CovarianceMatrix(final AbsoluteDate epoch,
471 final LOFType lofType, final Frame frame,
472 final RealMatrix lastMatrix) {
473 this.matrix = lastMatrix;
474 this.epoch = epoch;
475 this.lofType = lofType;
476 this.frame = frame;
477 }
478
479 /** Get the covariance matrix.
480 * @return the covariance matrix
481 */
482 public RealMatrix getMatrix() {
483 return matrix;
484 }
485
486 /** Get the epoch relative to the covariance matrix.
487 * @return the epoch
488 */
489 public AbsoluteDate getEpoch() {
490 return epoch;
491 }
492
493 /** Get coordinate system for covariance matrix, for Local Orbital Frames.
494 * <p>
495 * The value returned is null if the covariance matrix is given in an
496 * absolute frame rather than a Local Orbital Frame. In this case, the
497 * method {@link #getFrame()} must be used instead.
498 * </p>
499 * @return the coordinate system for covariance matrix, or null if the
500 * covariance matrix is given in an absolute frame rather than a Local
501 * Orbital Frame
502 */
503 public LOFType getLofType() {
504 return lofType;
505 }
506
507 /** Get coordinate system for covariance matrix, for absolute frames.
508 * <p>
509 * The value returned is null if the covariance matrix is given in a
510 * Local Orbital Frame rather than an absolute frame. In this case, the
511 * method {@link #getLofType()} must be used instead.
512 * </p>
513 * @return the coordinate system for covariance matrix
514 */
515 public Frame getFrame() {
516 return frame;
517 }
518
519 }
520
521
522 }